package ua.tach.shortl;

import ua.tach.shortl.logic.Country;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Matrix4;

public class Renderer {
	public static final int RAILMENU_SIZEX = 80;
	public static final int BANNER_SIZEY = 48;

	// Later we shall change to support different resolutions
	public static int screenSizeX = 800;
	public static int screenSizeY = 480;

	/* ViewPort parameters */
	private static final int vp1X1 = RAILMENU_SIZEX; // Main screen
	private static final int vp1Y1 = BANNER_SIZEY;
	private static final int vp1X2 = Gdx.graphics.getWidth()-RAILMENU_SIZEX;
	private static final int vp1Y2 = Gdx.graphics.getHeight()-BANNER_SIZEY;

	private static final int vp2X1 = 0; // Control screen
	private static final int vp2Y1 = BANNER_SIZEY;
	private static final int vp2X2 = RAILMENU_SIZEX;
	private static final int vp2Y2 = Gdx.graphics.getHeight()-BANNER_SIZEY;

	private static final int vp3X1 = 0; // Banner screen
	private static final int vp3Y1 = 0;
	private static final int vp3X2 = Gdx.graphics.getWidth();
	private static final int vp3Y2 = BANNER_SIZEY;

	// coordinates for control menu
	private static final int vp4X1 = 250; //
	private static final int vp4Y1 = 200;
	private static final int vp4X2 = 320;
	private static final int vp4Y2 = 256;

	/** sprite batch to draw text **/
	private SpriteBatch spriteBatch;
	private TextureRegion controlsTexture;
	/** the background texture **/
	private Texture backgroundTexture;

	/** view and transform matrix for text rendering **/
	private Matrix4 viewMatrix2 = new Matrix4();
	private Matrix4 viewMatrix3 = new Matrix4();
	private Matrix4 viewMatrix4 = new Matrix4();
	private Mesh bgMesh;

	public static OrthographicCamera camera;

	private RenderCounter cntYears = new RenderCounter(379, 4, 4, 0);
	private RenderCounter cntTrains = new RenderCounter(466, 4, 4, 1);
	private Bank cntMoney = new Bank(573, 4, 4, 100);
	private RenderCounter cntLvl = new RenderCounter(650, 4, 2, 2);

	public static Loader[] toLoad = {
		// -- 0 --
		new Loader("railr"), //0 ( Rail.mesh[0], "railr" , Rail.texture[0] ),
		new Loader("rails"), // ( Rail.mesh[1], "rails" , Rail.texture[1] ),
		new Loader("tree"), // Trees
		new Loader("yolka"), // Trees
		new Loader("house"), // ( CityPlace.meshHouse, "house", CityPlace.texture ),
		// -- 5 --
		new Loader("parovoz"), // ( Train.meshLoco, "parovoz" , Train.textureLoco	), t0
		new Loader("parovoz"), // lokomotiv
		new Loader("kupe"), // skorij t2
		new Loader("kupe"), // tramwaj
		new Loader("kupe"), // cisterna t4
		// -- 10 --
		new Loader("kupe"), // platforma
		new Loader("kupe"), // kupe t6
		new Loader("drezina"), // drezina t7
		// strelki ->
		new Loader("light-green"), //
		new Loader("light-red"), //
		// -- 15 --
		new Loader("sw-right"), //
		new Loader("sw-left"), //
		new Loader("sw-fw"), //
		new Loader("tupik1"), //
		// -- 19 --
		new Loader("crash"), // Crash sign
		new Loader("cone"), // Waiting train
		new Loader("cone"), // ( Country.mesh, "cone", Country.texture),
		new Loader("cube"), // ( Link.mesh, "cube", Link.texture),
	};

	public Renderer (Application app) {
		screenSizeX = Gdx.graphics.getWidth();
		screenSizeY = Gdx.graphics.getHeight();

		try {
			spriteBatch = new SpriteBatch();

			controlsTexture = new TextureRegion(new Texture(Gdx.files.internal("data/gameover.png"), true),0,0,245,255);

			setScreen();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public void render (Application app) {
		GL10 gl = app.getGraphics().getGL10();
		gl.glViewport(vp1X1, vp1Y1, vp1X2, vp1Y2);
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

		camera.update();
		camera.apply(gl);

		gl.glEnable(GL10.GL_TEXTURE_2D);
		backgroundTexture.bind();
		bgMesh.render(GL10.GL_TRIANGLES);
		gl.glEnable(GL10.GL_DEPTH_TEST);
		gl.glEnable(GL10.GL_CULL_FACE);
		Country.render(gl);
		gl.glDisable(GL10.GL_TEXTURE_2D);
		gl.glDisable(GL10.GL_CULL_FACE);
		gl.glDisable(GL10.GL_DEPTH_TEST);

		renderMenu(gl);
		renderCounters(gl);

		if (Country.gamePause) {
			gl.glViewport(vp4X1, vp4Y1, vp4X2, vp4Y2);
			spriteBatch.setProjectionMatrix(viewMatrix4);
			spriteBatch.begin();
			spriteBatch.draw(TextureLoader.gameMenuTexture[0], vp4X1, vp4Y1+96);
			spriteBatch.draw(TextureLoader.gameMenuTexture[1], vp4X1, vp4Y1+64);
			spriteBatch.draw(TextureLoader.gameMenuTexture[1], vp4X1, vp4Y1+32);
			spriteBatch.draw(TextureLoader.gameMenuTexture[2], vp4X1, vp4Y1);
			spriteBatch.end();
		}
	}

	private void renderMenu(GL10 gl)
	{
		gl.glViewport(vp2X1, vp2Y1, vp2X2, vp2Y2);
		spriteBatch.setProjectionMatrix(viewMatrix2);
		spriteBatch.begin();
		spriteBatch.draw(TextureLoader.menuTexture, 0,48);
		spriteBatch.end();
	}

	private void renderCounters(GL10 gl)
	{
		gl.glViewport(vp3X1, vp3Y1, vp3X2, vp3Y2);
		spriteBatch.setProjectionMatrix(viewMatrix3);
		spriteBatch.begin();
		cntYears.render(spriteBatch);
		cntTrains.render(spriteBatch);
		cntMoney.render(spriteBatch);
		cntLvl.render(spriteBatch);
		spriteBatch.draw(TextureLoader.bannerPlTexture, 0,0);
		for (int i=0; i < 6; ++i) {
			int wt = Country.getWaitingTrain(i);
			if (wt == 2) continue;
			spriteBatch.setColor( Country.CITY_COLORS[i].x, Country.CITY_COLORS[i].y, Country.CITY_COLORS[i].z, 1);
			spriteBatch.draw(TextureLoader.entersTexture[wt], 676 + 20*i, 2);
		}
		spriteBatch.setColor( 1, 1, 1, 1);
		spriteBatch.end();
	}

	public void dispose () {
		spriteBatch.dispose();
		backgroundTexture.dispose();
		for (Loader mm : toLoad)
			mm.m.dispose();
	}

	/*
	 * Calculate screen size and camera angles, initialise background meshes
	 */
	public static float SCENE_A = 5.4f; // 6- debug, 5.4 -release
	public static float SCENE_B = 4.2f; // 8.7
	public void setScreen () {

		/* set viewports */
		viewMatrix2.setToOrtho2D(vp2X1, vp2Y1, vp2X2, vp2Y2);
		viewMatrix3.setToOrtho2D(vp3X1, vp3Y1, vp3X2, vp3Y2);
		viewMatrix4.setToOrtho2D(vp4X1, vp4Y1, vp4X2, vp4Y2);

		/* Camera setup */
		camera = new OrthographicCamera( SCENE_A, SCENE_B);
		camera.near = 0.1f;
		camera.far = 100.0f;

//		double pN = (ext_y * Country.COUNTRY_SIZE * Math.sqrt(2) )/ (Country.SCENE_A *
//				Math.sqrt(1-(ext_y*ext_y/(Country.SCENE_A*Country.SCENE_A))));

		float pN = 5.7f;
		float lookAt = 4f;

		camera.position.set(-Country.COUNTRY_SIZE/2, pN, -Country.COUNTRY_SIZE/2);
		camera.lookAt(lookAt, 0.0f ,lookAt);
		camera.update();
		camera.apply(Gdx.gl10);

		/* Background setup */
		backgroundTexture = new Texture(Gdx.files.internal("data/bg2.png"), true);
		backgroundTexture.setFilter(TextureFilter.MipMap, TextureFilter.Linear);

		bgMesh = new Mesh(true, 4, 6, new VertexAttribute(Usage.Position, 3, "a_pos"),
				new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoord"));
		bgMesh.setVertices(new float[] {
			-2, 0,  Country.COUNTRY_SIZE, 1, 1,
			Country.COUNTRY_SIZE, 0,  Country.COUNTRY_SIZE, 1, 0,
			Country.COUNTRY_SIZE, 0,  -2, 0, 0,
			-2, 0, -2,0,1
		});
		bgMesh.setIndices(new short[] { 0, 1, 2, 2, 3, 0 });

		Country.init (cntYears, cntTrains, cntMoney);
	}
}
